﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace WoWConnecter
{
    /// <summary>
    /// Allows a connection the the authentication server
    /// </summary>
    public partial class AuthClient : BaseClient
    {
        private Dictionary<string, Realm> mRealms;

        public event Action<AccountStatus> LoginResult;
        public event Action<Realm[]> RealmSelection;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="username">Username of your account</param>
        /// <param name="password">Password of your username</param>
        public AuthClient(string username, string password)
            : base(username, password)
        {
            PacketHandler = new PacketHandler();
            PacketHandler.Load(this);
        }

        /// <summary>
        /// Connects to a realmlist
        /// </summary>
        /// <param name="realmlist"></param>
        public override void Connect(string realmlist)
        {
            mRealms = new Dictionary<string, Realm>();
            base.Connect(realmlist);
            LoginChallenge();
        }

        protected override void OnReceive(IAsyncResult result)
        {
            int received = mStream.EndRead(result);

            var packet = new AuthPacketIn(mBuffer, received);
            packet.FinalizePacket();
            HandlePacket(packet);
            BeginReceive();
        }

        /// <summary>
        /// Starts the connection to a realm
        /// </summary>
        /// <param name="realm">Realm to connect to</param>
        /// <returns><see cref="RealmClient">RealmClient</see> connected to specified realm</returns>
        public RealmClient RealmSelect(Realm realm)
        {
            RealmClient client = new RealmClient(this, SecurePassword, PacketHandler, realm);

            return client;
        }

        /// <summary>
        /// Sends the packet to challenge the login, this is cal
        /// </summary>
        private void LoginChallenge()
        {
            var packet = new AuthPacketOut(AuthServerOpCode.AUTH_LOGON_CHALLENGE);

            packet.WriteByte(0);

            packet.WriteUShort(30 + Username.Length);                                                        // Packet size + name length

            packet.Write("WoW");        // WoW

            packet.WriteByte(3);
            packet.WriteByte(3);
            packet.WriteByte(2);
            packet.WriteUShort(11403);

            packet.Write("68x");
            packet.Write("niW");

            packet.WriteString("SUne");

            packet.Write(1);

            packet.WriteByte(192);
            packet.WriteByte(168);
            packet.WriteByte(1);
            packet.WriteByte(100);

            packet.WriteByteString(Username);

            Send(packet);
        }

        private byte[] GenerateCrc(byte[] crcsalt)
        {
            Sha1Hash sha;

            byte[] buffer1 = new byte[0x40];
            byte[] buffer2 = new byte[0x40];

            for (int i = 0; i < 0x40; ++i)
            {
                buffer1[i] = 0x36;
                buffer2[i] = 0x5c;
            }

            for (int i = 0; i < crcsalt.Length; ++i)
            {
                buffer1[i] ^= crcsalt[i];
                buffer2[i] ^= crcsalt[i];
            }

            sha = new Sha1Hash();
            sha.Update(buffer1);

            byte[] hash1 = sha.Final();

            sha = new Sha1Hash();
            sha.Update(buffer2);
            sha.Update(hash1);
            return sha.Final();
        }

        //private byte[] GenerateCrc(byte[] crcsalt)
        //{
        //    Sha1Hash sha;

        //    byte[] buffer1 = new byte[0x40];
        //    byte[] buffer2 = new byte[0x40];

        //    for (int i = 0; i < 0x40; ++i)
        //    {
        //        buffer1[i] = 0x36;
        //        buffer2[i] = 0x5c;
        //    }

        //    for (int i = 0; i < crcsalt.Length; ++i)
        //    {
        //        buffer1[i] ^= crcsalt[i];
        //        buffer2[i] ^= crcsalt[i];
        //    }

        //    sha = new Sha1Hash();
        //    sha.Update(buffer1);


        //    try
        //    {
        //        FileStream fs = new FileStream("hash.bin", FileMode.Open, FileAccess.Read);
        //        byte[] Buffer = new byte[fs.Length];
        //        fs.Read(Buffer, 0, (int)fs.Length);
        //        sha.Update(Buffer);
        //    }
        //    catch (Exception e)
        //    {

        //    }

        //    byte[] hash1 = sha.Final();

        //    sha = new Sha1Hash();
        //    sha.Update(buffer2);
        //    sha.Update(hash1);
        //    return sha.Final();
        //}
    }
}
